#!/bin/bash

# Vault MySQL高并发服务 - 部署脚本
# 用于自动化部署和管理应用服务

set -e  # 遇到错误立即退出

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 配置变量
APP_NAME="vault-mysql-service"
DOCKER_IMAGE="vault-mysql-service:latest"
COMPOSE_FILE="docker-compose.yml"
ENV_FILE=".env"
BACKUP_DIR="./backups"
LOG_DIR="./logs"

# 函数：打印带颜色的消息
print_message() {
    local color=$1
    local message=$2
    echo -e "${color}[$(date +'%Y-%m-%d %H:%M:%S')] ${message}${NC}"
}

print_info() {
    print_message $BLUE "$1"
}

print_success() {
    print_message $GREEN "$1"
}

print_warning() {
    print_message $YELLOW "$1"
}

print_error() {
    print_message $RED "$1"
}

# 函数：检查依赖
check_dependencies() {
    print_info "检查系统依赖..."
    
    # 检查Docker
    if ! command -v docker &> /dev/null; then
        print_error "Docker未安装，请先安装Docker"
        exit 1
    fi
    
    # 检查Docker Compose
    if ! command -v docker-compose &> /dev/null; then
        print_error "Docker Compose未安装，请先安装Docker Compose"
        exit 1
    fi
    
    # 检查Maven（如果需要本地构建）
    if [[ "$1" == "build" ]] && ! command -v mvn &> /dev/null; then
        print_error "Maven未安装，请先安装Maven或使用Docker构建"
        exit 1
    fi
    
    print_success "依赖检查完成"
}

# 函数：创建必要的目录
create_directories() {
    print_info "创建必要的目录..."
    
    mkdir -p $BACKUP_DIR
    mkdir -p $LOG_DIR
    mkdir -p ./vault-config
    mkdir -p ./mysql-config
    mkdir -p ./mysql-init
    mkdir -p ./nginx
    mkdir -p ./monitoring
    
    print_success "目录创建完成"
}

# 函数：生成环境配置文件
generate_env_file() {
    print_info "生成环境配置文件..."
    
    if [[ ! -f $ENV_FILE ]]; then
        cat > $ENV_FILE << EOF
# Vault MySQL服务环境配置

# 应用配置
SPRING_PROFILES_ACTIVE=docker
SERVER_PORT=8080

# Vault配置
VAULT_URL=http://vault:8200
VAULT_TOKEN=myroot

# 数据库配置
MYSQL_ROOT_PASSWORD=rootpassword
MYSQL_DATABASE=testdb
MYSQL_USER=testuser
MYSQL_PASSWORD=testpassword

# Redis配置
REDIS_PASSWORD=redispassword

# 监控配置
GRAFANA_ADMIN_PASSWORD=admin

# 应用特定配置
APP_INIT_DATA_ON_STARTUP=true
APP_MAX_CONCURRENT_TESTS=10
APP_DEFAULT_TEST_DURATION=300

# 日志级别
LOGGING_LEVEL_ROOT=INFO
LOGGING_LEVEL_COM_EXAMPLE_VAULTMYSQL=DEBUG
EOF
        print_success "环境配置文件已生成: $ENV_FILE"
    else
        print_warning "环境配置文件已存在: $ENV_FILE"
    fi
}

# 函数：生成MySQL配置文件
generate_mysql_config() {
    print_info "生成MySQL配置文件..."
    
    # 主数据库配置
    cat > ./mysql-config/primary.cnf << EOF
[mysqld]
server-id=1
log-bin=mysql-bin
binlog-format=ROW
max_connections=1000
innodb_buffer_pool_size=256M
innodb_log_file_size=64M
innodb_flush_log_at_trx_commit=2
sync_binlog=1
EOF

    # 从数据库配置
    cat > ./mysql-config/replica.cnf << EOF
[mysqld]
server-id=2
relay-log=mysql-relay-bin
log-slave-updates=1
read_only=1
max_connections=1000
innodb_buffer_pool_size=256M
innodb_log_file_size=64M
EOF

    print_success "MySQL配置文件已生成"
}

# 函数：生成初始化SQL脚本
generate_init_sql() {
    print_info "生成数据库初始化脚本..."
    
    cat > ./mysql-init/01-init.sql << EOF
-- 创建测试数据库和用户
CREATE DATABASE IF NOT EXISTS testdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'testuser'@'%' IDENTIFIED BY 'testpassword';
GRANT ALL PRIVILEGES ON testdb.* TO 'testuser'@'%';
FLUSH PRIVILEGES;

-- 创建性能测试表
USE testdb;

CREATE TABLE IF NOT EXISTS performance_test (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    test_name VARCHAR(255) NOT NULL,
    test_data TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_test_name (test_name),
    INDEX idx_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 插入测试数据
INSERT INTO performance_test (test_name, test_data) VALUES
('test1', 'Sample test data 1'),
('test2', 'Sample test data 2'),
('test3', 'Sample test data 3');
EOF

    print_success "数据库初始化脚本已生成"
}

# 函数：构建应用
build_app() {
    print_info "构建应用..."
    
    if [[ "$1" == "local" ]]; then
        # 本地Maven构建
        print_info "使用Maven进行本地构建..."
        mvn clean package -DskipTests
        print_success "Maven构建完成"
    fi
    
    # Docker构建
    print_info "构建Docker镜像..."
    docker build -t $DOCKER_IMAGE .
    print_success "Docker镜像构建完成"
}

# 函数：启动服务
start_services() {
    print_info "启动服务..."
    
    # 检查是否已有运行的容器
    if docker-compose ps | grep -q "Up"; then
        print_warning "检测到运行中的容器，将先停止现有服务"
        docker-compose down
    fi
    
    # 启动服务
    docker-compose up -d
    
    print_success "服务启动完成"
    
    # 等待服务就绪
    print_info "等待服务就绪..."
    sleep 30
    
    # 检查服务状态
    check_services_health
}

# 函数：停止服务
stop_services() {
    print_info "停止服务..."
    docker-compose down
    print_success "服务已停止"
}

# 函数：重启服务
restart_services() {
    print_info "重启服务..."
    stop_services
    start_services
}

# 函数：检查服务健康状态
check_services_health() {
    print_info "检查服务健康状态..."
    
    local services=("vault-mysql-app" "vault-server" "mysql-primary")
    local all_healthy=true
    
    for service in "${services[@]}"; do
        if docker ps --filter "name=$service" --filter "status=running" | grep -q $service; then
            print_success "✓ $service 运行正常"
        else
            print_error "✗ $service 运行异常"
            all_healthy=false
        fi
    done
    
    if $all_healthy; then
        print_success "所有核心服务运行正常"
        print_info "应用访问地址: http://localhost:8080"
        print_info "Vault访问地址: http://localhost:8200"
        print_info "Grafana访问地址: http://localhost:3000 (admin/admin)"
    else
        print_error "部分服务运行异常，请检查日志"
    fi
}

# 函数：查看日志
view_logs() {
    local service=$1
    if [[ -z $service ]]; then
        print_info "查看所有服务日志..."
        docker-compose logs -f
    else
        print_info "查看 $service 服务日志..."
        docker-compose logs -f $service
    fi
}

# 函数：备份数据
backup_data() {
    print_info "备份数据..."
    
    local backup_file="$BACKUP_DIR/backup-$(date +%Y%m%d-%H%M%S).tar.gz"
    
    # 创建备份
    docker run --rm \
        -v vault-mysql-service_mysql-primary-data:/data \
        -v $(pwd)/$BACKUP_DIR:/backup \
        alpine tar czf /backup/$(basename $backup_file) -C /data .
    
    print_success "数据备份完成: $backup_file"
}

# 函数：恢复数据
restore_data() {
    local backup_file=$1
    
    if [[ -z $backup_file ]] || [[ ! -f $backup_file ]]; then
        print_error "请指定有效的备份文件"
        exit 1
    fi
    
    print_warning "恢复数据将覆盖现有数据，确认继续？(y/N)"
    read -r confirm
    if [[ $confirm != "y" ]] && [[ $confirm != "Y" ]]; then
        print_info "操作已取消"
        exit 0
    fi
    
    print_info "恢复数据: $backup_file"
    
    # 停止服务
    docker-compose down
    
    # 恢复数据
    docker run --rm \
        -v vault-mysql-service_mysql-primary-data:/data \
        -v $(pwd)/$BACKUP_DIR:/backup \
        alpine sh -c "rm -rf /data/* && tar xzf /backup/$(basename $backup_file) -C /data"
    
    # 重启服务
    start_services
    
    print_success "数据恢复完成"
}

# 函数：清理资源
cleanup() {
    print_warning "清理所有资源（包括数据卷），确认继续？(y/N)"
    read -r confirm
    if [[ $confirm != "y" ]] && [[ $confirm != "Y" ]]; then
        print_info "操作已取消"
        exit 0
    fi
    
    print_info "清理资源..."
    
    # 停止并删除容器、网络、数据卷
    docker-compose down -v --remove-orphans
    
    # 删除镜像
    if docker images | grep -q $DOCKER_IMAGE; then
        docker rmi $DOCKER_IMAGE
    fi
    
    print_success "资源清理完成"
}

# 函数：显示帮助信息
show_help() {
    echo "Vault MySQL高并发服务 - 部署脚本"
    echo ""
    echo "用法: $0 [命令] [选项]"
    echo ""
    echo "命令:"
    echo "  init                初始化项目（创建配置文件和目录）"
    echo "  build [local]       构建应用（可选local进行本地Maven构建）"
    echo "  start               启动所有服务"
    echo "  stop                停止所有服务"
    echo "  restart             重启所有服务"
    echo "  status              检查服务状态"
    echo "  logs [service]      查看日志（可指定服务名）"
    echo "  backup              备份数据"
    echo "  restore <file>      恢复数据"
    echo "  cleanup             清理所有资源"
    echo "  help                显示帮助信息"
    echo ""
    echo "示例:"
    echo "  $0 init             # 初始化项目"
    echo "  $0 build            # 构建应用"
    echo "  $0 start            # 启动服务"
    echo "  $0 logs app         # 查看应用日志"
    echo "  $0 backup           # 备份数据"
    echo ""
}

# 主函数
main() {
    local command=$1
    local option=$2
    
    case $command in
        "init")
            check_dependencies
            create_directories
            generate_env_file
            generate_mysql_config
            generate_init_sql
            print_success "项目初始化完成"
            ;;
        "build")
            check_dependencies "build"
            build_app $option
            ;;
        "start")
            check_dependencies
            start_services
            ;;
        "stop")
            stop_services
            ;;
        "restart")
            restart_services
            ;;
        "status")
            check_services_health
            ;;
        "logs")
            view_logs $option
            ;;
        "backup")
            backup_data
            ;;
        "restore")
            restore_data $option
            ;;
        "cleanup")
            cleanup
            ;;
        "help"|"--help"|"-h")
            show_help
            ;;
        "")
            print_error "请指定命令，使用 '$0 help' 查看帮助"
            exit 1
            ;;
        *)
            print_error "未知命令: $command"
            show_help
            exit 1
            ;;
    esac
}

# 脚本入口
main "$@"